/*
ID: khymill1
PROG: cowtour 
LANG: C++
*/
#include <string.h>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>


using namespace std;

typedef struct point {
    int x, y;
    point(int x, int y):x(x), y(y){}
    point(){};
} point_t;

double dis(point_t &a, point_t &b)
{
    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}

void floyd( vector<vector<double> > &adj)
{
	int n = adj.size();
	
	for (int k = 0; k < n; k++) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i != j)
					adj[i][j] = min(adj[i][j], adj[i][k] + adj[k][j]);
			}
		}
	}


}
int color[150];
int size;

void make_color(int i,int c, vector<vector<char> > &adj1)
{
    if( color[i]!=0 )
        return;

    color[i] = c;

    for(int j=0; j< adj1.size();++j){
        if(color[j]==0&& adj1[i][j] == '1')
            make_color(j,c, adj1);
    }
}
double diameter[150];
int main()
{
    ifstream fin("cowtour.in");
    ofstream fout("cowtour.out");
    int n;
    fin >> n;
	size = n;
    vector<point_t> points(n);
    vector<vector<double> > adj(n, vector<double>(n, INT_MAX));
	vector<vector<char> > adj1(n, vector<char>(n));
    for (int i = 0; i < n; i++) {
	fin >> points[i].x >> points[i].y;
    }	

    for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
	    fin >> adj1[i][j];
	    if (adj1[i][j] == '1') {
			adj[i][j] = dis(points[i], points[j]);   
	    }
		}
    }	
	floyd(adj);

    int c = 0;
    for(int i=0;i<n;++i)
        if(color[i]==0)
            make_color(i,++c, adj1);

	for (int i = 0; i < n; i++) {
		double maxPath = 0;
		if (i == 5)
			int test = 0;
		for (int j = 0; j < n; j++) {
			if (i != j && color[i] == color[j])
				maxPath = max(maxPath,adj[i][j]);
		}
		diameter[color[i]] = max(diameter[color[i]], maxPath);
	}

	double dia = INT_MAX;
	for (int i = 0; i < n; i++) {
		for (int j = i+1; j < n; j++) {
			if (color[i] == color[j]) continue;

			double p1 = 0;
			for (int k = 0; k < n; k++) {
				if (i != k && color[i] == color[k])
					p1 = max(p1, adj[i][k]);
			}
			double p2 = 0;
			for (int k = 0; k < n; k++) {
				if (j != k && color[j] == color[k])
					p2 = max(p2, adj[j][k]);
			}
			double dist = dis(points[i], points[j]);
			dia = min(dia, max(p1+p2+dist, max(diameter[color[i]], diameter[color[j]])));
		}
	}
    fout.setf(ios::fixed,ios::floatfield);
    fout.precision(6);
    fout<<dia<<endl;
    //cout.setf(ios::fixed,ios::floatfield);
    //cout.precision(6);
    //cout<<dia<<endl;
    return 0;
}
